package com.fa4j.system.file.service.impl;

import com.alibaba.fastjson2.JSON;
import com.fa4j.common.base.exception.CommonRequestError;
import com.fa4j.common.base.model.RemoveCmd;
import com.fa4j.system.file.convert.SysFileConverter;
import com.fa4j.system.file.model.SysFile;
import com.fa4j.system.file.model.SysFileUploadCmd;
import com.fa4j.system.file.repository.SysFileRepository;
import com.fa4j.system.file.service.SysFileService;
import com.fa4j.third.file.model.ThirdFileDownloadCmd;
import com.fa4j.third.file.model.ThirdFileRemoveCmd;
import com.fa4j.third.file.model.ThirdFileUploadCmd;
import com.fa4j.third.file.model.ThirdFileUrlCmd;
import com.fa4j.third.file.service.ThirdFileService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;

import java.io.ByteArrayInputStream;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.Date;
import java.util.Optional;
import java.util.UUID;

/**
 * 系统文件 服务接口实现
 *
 * @since 2025-06-12 08:59:45
 */
@Slf4j
@Service
@Validated
@RequiredArgsConstructor
public class SysFileServiceImpl implements SysFileService {

    private static final String FILE_PATH_TEMPLATE = "/{0,date,yyyy-MM-dd}/{1}.{2}";

    private final ThirdFileService thirdFileService;
    private final SysFileRepository sysFileRepository;
    private final SysFileConverter sysFileConverter;

    /**
     * 系统文件删除
     *
     * @param cmd 系统文件删除参数
     * @return 系统文件
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SysFile remove(@Valid RemoveCmd<Long> cmd) {
        SysFile entity = sysFileRepository.findById(cmd.getId())
                .orElseThrow(() -> CommonRequestError.NOT_FOUND.build("系统文件"));
        entity.setOperatorId(cmd.getOperatorId());
        sysFileRepository.remove(entity);
        ThirdFileRemoveCmd thirdFileRemoveCmd = new ThirdFileRemoveCmd();
        thirdFileRemoveCmd.setBizCode(entity.getFileGroup());
        thirdFileRemoveCmd.setFilePath(entity.getFilePath());
        thirdFileService.remove(thirdFileRemoveCmd);
        return entity;
    }

    /**
     * 文件上传
     *
     * @param cmd 参数
     * @return 上传文件
     */
    @Override
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public SysFile upload(SysFileUploadCmd cmd) {
        SysFile sysFile;
        byte[] bytes = StreamUtils.copyToByteArray(cmd.getInputStream());
        String md5 = DigestUtils.md5DigestAsHex(bytes);
        String fileExtension = StringUtils.getFilenameExtension(cmd.getFileName());
        Optional<SysFile> existFile = sysFileRepository.findByNameAndMd5(cmd.getFileGroup(), cmd.getFileName(), md5);
        if (existFile.isPresent()) {
            sysFile = existFile.get();
            log.info("文件已经上传:{}", JSON.toJSONString(existFile));
        } else {
            String filePath = MessageFormat.format(FILE_PATH_TEMPLATE, new Date(), UUID.randomUUID().toString().replaceAll("-", ""), fileExtension);

            ThirdFileUploadCmd thirdFileUploadCmd = new ThirdFileUploadCmd();
            thirdFileUploadCmd.setBizCode(cmd.getFileGroup());
            thirdFileUploadCmd.setFilePath(filePath);
            thirdFileUploadCmd.setContentType(cmd.getContentType());
            thirdFileUploadCmd.setFileExtension(fileExtension);
            thirdFileUploadCmd.setFileSize(cmd.getFileSize());
            thirdFileService.upload(thirdFileUploadCmd, new ByteArrayInputStream(bytes));

            sysFile = sysFileConverter.toModel(cmd);
            sysFile.setFileMd5(md5);
            sysFile.setFilePath(filePath);
            sysFileRepository.create(sysFile);
        }
        ThirdFileUrlCmd thirdFileUrlCmd = new ThirdFileUrlCmd();
        thirdFileUrlCmd.setFilePath(sysFile.getFilePath());
        thirdFileUrlCmd.setBizCode(sysFile.getFileGroup());
        sysFile.setFileUrl(thirdFileService.getFileUrl(thirdFileUrlCmd));
        return sysFile;
    }

    /**
     * 下载文件
     *
     * @param sysFile      文件
     * @param outputStream 文件输出流
     */
    @Override
    public void download(SysFile sysFile, OutputStream outputStream) {
        ThirdFileDownloadCmd thirdFileDownloadCmd = new ThirdFileDownloadCmd();
        thirdFileDownloadCmd.setFilePath(sysFile.getFilePath());
        thirdFileDownloadCmd.setBizCode(sysFile.getFileGroup());
        thirdFileService.download(thirdFileDownloadCmd, outputStream);
    }

    /**
     * 设置文件地址
     *
     * @param sysFile 文件
     */
    @Override
    public SysFile setFileUrl(SysFile sysFile) {
        ThirdFileUrlCmd thirdFileUrlCmd = new ThirdFileUrlCmd();
        thirdFileUrlCmd.setFilePath(sysFile.getFilePath());
        thirdFileUrlCmd.setBizCode(sysFile.getFileGroup());
        String fileUrl = thirdFileService.getFileUrl(thirdFileUrlCmd);
        sysFile.setFileUrl(fileUrl);
        return sysFile;
    }

}




